/*****************************************
**  Nom : RASPAUD - COLLOMB				**
**	Nom du fichier : InitPartie.c		**
**	Description : Regroupe toutes les	**
**				  fonctions 			**
**				  d'initialisation		**
**										**
**	Date : 19/08/2014				    **
**  Statut : Release					**
*****************************************/

/*****************************************
**  Zone de declaration des includes    **
*****************************************/
#include "struct.h"

/*************************************************
**  Zone de declaration des Fonctions PUBLIC    **
*************************************************/

/*************************************************************************
**  [Fonction InitPartie_InitCarte]        		    					**
**  Création d'une carte										        **
**																		**
**	Entrees : int valeur - Valeur des cartes	                        **
**			: int signe - Signe des cartes								**
**																		**
**	Sorties : S_CARTE													**
**				Description de la carte créée                           **
**										                                **
**************************************************************************/

S_CARTE* InitPartie_InitCarte(int valeur, int signe)
{
	S_CARTE *carte;
	
	carte=(S_CARTE*)malloc(sizeof(S_CARTE));
	if(carte==NULL)
	{
		printf("ERROR !\n");
		return NULL;
	}
	carte->valeur=valeur;
	carte->signe=signe;
	return carte;
}


/*************************************************************************
**  [Fonction InitPartie_InitPaquet]       		    					**
**  Création d'un paquet 										        **
**																		**
**	Entrees : FIFO_PAQUET paquet - La FIFO "table"	      	            **
**																		**
**																		**
**	Sorties : FIFO_PAQUET												**
**				Description d'un paquet de carte                        **
**										                                **
**************************************************************************/

int InitPartie_InitPaquet(FIFO_PAQUET *paquet)
{
	int random_s=0,random_v=0,flag=0,i=1;
	int tab[NOMBRE_SIGNE][NOMBRE_CARTE];
	S_CARTE *nouvelle_carte,*carte_courante;
	
	//printf("InitPartie_InitPaquet : Début Fonction\n");
	while(i<=NOMBRE_CARTE_TOTAL)
	{
		while(flag==0)
		{
			random_s=DrlmntPartie_Random(NOMBRE_SIGNE); //de 1 à 4
			random_v=DrlmntPartie_Random(NOMBRE_CARTE); // de 1 à 13
	
			if(tab[NOMBRE_SIGNE][NOMBRE_CARTE]==1)
			{
				//printf("InitPartie_InitPaquet : carte déjà créée !\n");
				flag=0;
			}
			else
				flag=1;
		}
	
		flag=0;
	
		//printf("InitPartie_InitPaquet : lancement de la fonction init_carte\n");
		nouvelle_carte=InitPartie_InitCarte(random_v,random_s);
		if(nouvelle_carte==NULL)
		{
			printf("InitPartie_InitPaquet : Erreur lors de la création de la carte ! !\n");
			return -1;
		}
		//printf("InitPartie_InitPaquet : fin de la fonction init_carte\n");
			
		//printf("InitPartie_InitPaquet : signe %d sur valeur %d et appartient au joueur %d\n",random_s,random_v,paquet->nom_joueur);
	
		if(paquet->carte_in==NULL && paquet->carte_out==NULL) //1ere carte mise dans le paquet
		{
			//printf("InitPartie_InitPaquet : Début 1er mise dans paquet\n");
			paquet->nb_carte++;
			paquet->carte_in=nouvelle_carte;
			paquet->carte_out=nouvelle_carte;
			//printf("InitPartie_InitPaquet : affectation 1ere carte OK\n");
		}
		else //mise en tête du paquet
		{
			//printf("InitPartie_InitPaquet : Début mise dans paquet\n");
			paquet->nb_carte++;
			carte_courante=paquet->carte_in;
			paquet->carte_in=nouvelle_carte;
			nouvelle_carte->carte_suivante=carte_courante;
			//printf("InitPartie_InitPaquet : affectation carte OK\n");
		}
		i++;
	}
	//printf("InitPartie_InitPaquet : Fin Fonction !\n");
	return 0;
}


/*************************************************************************
**  [Fonction InitPartie_InitFIFO]       		    					**
**  Création et initialisation d'une FIFO correspondant a un joueur     **
**																		**
**	Entrees : int *nom_joueur - Identification d'un joueur via un numero**
**																		**
**																		**
**	Sorties : FIFO_PAQUET												**
**				Description d'un joueur avec ses cartes                 **
**										                                **
**************************************************************************/

FIFO_PAQUET InitPartie_InitFIFO(int nom_joueur)
{
	FIFO_PAQUET FIFO; //sera un élément du paquet pour distribuer ET pour poser les cartes durant la partie !!!
	
	//printf("InitPartie_InitFIFO : FIFO créer --> mise en mémoire\n");
	FIFO.nom_joueur=nom_joueur;
	FIFO.nb_carte=0;
	FIFO.carte_in=NULL;
	FIFO.carte_out=NULL;
	//printf("InitPartie_InitFIFO : Fin fonction --> envoi de la FIFO OK !\n");
	return FIFO;
}

/*************************************************************************
**  InitPartie_InitPartie			                		    					**
**  Description de la fonction	:initialise tous les 
	paquets de cartes 													**
**																		**
**	Entrees : FIFO_PAQUET --> FIFO du paquet "table" 					**
**			  FIFO_PAQUET --> FIFO du paquet "J1" 	
			  FIFO_PAQUET --> FIFO du paquet "J2" 
			  FIFO_PAQUET --> FIFO du paquet "J3" 
			  FIFO_PAQUET --> FIFO du paquet "J4" 						**
**																		**
**	Sorties : int --> si -1=Erreur // si 0-OK							**
**									                                    **
**									                                    **
**************************************************************************/
int InitPartie_InitPartie(FIFO_PAQUET *table, FIFO_PAQUET *J1, FIFO_PAQUET *J2, FIFO_PAQUET *J3, FIFO_PAQUET *J4)
{
	int test=-1,random=0,i=1,valid[NOMBRE_JOUEUR],nb_joueur_actif=0;
	int nb_carte=0;
	
	memset(valid,0,sizeof(valid));
	test=InitPartie_InitPaquet(table);
	if(test==-1)
	{
		printf("InitPartie_InitPartie : Erreur lors de l'init du paquet table !\n");
		return -1;
	}
	//printf("InitPartie_InitPartie : table.nb_carte = %d \n",table->nb_carte);
	
	nb_joueur_actif=InitPartie_Compte_Joueur(J1,J2,J3,J4); //renvoi le nombre de joueur ACTIF
	
	// 52 cartes / 4 = 13 cartes par personne
	// 52 cartes / 3 = 17 cartes par personnes + 1 carte à un joueur
	// 52 cartes / 2 = 26 cartes par personnes
	
	switch(nb_joueur_actif)
	{
		case 2: nb_carte=26;
				break;
		case 3: nb_carte=17;
				break;
		case 4: nb_carte=13;
				break;
		default: printf("InitPartie_InitPartie : Erreur ! Nombre de joueur incorrect !\n");
				 return -1;
	}
	
	srand(time(NULL)); //ligne obligatoire pour que le nombre retourné par DrlmntPartie_Random soit différent à chaque appel
	while(i<=nb_carte)
	{
		/*printf("InitPartie_InitPartie : i=%d\n",i);
		DrlmntPartie_AfficheFIFO(table);
		printf("InitPartie_InitPartie : nb_carte de table=%d\n",table->nb_carte);*/
		while(((valid[0]!=1 || valid[1]!=1 || valid[2]!=1 || valid[3]!=1) && nb_joueur_actif==4) || ((valid[0]!=1 || valid[1]!=1 || valid[2]!=1) && nb_joueur_actif==3) || ((valid[0]!=1 || valid[1]!=1) && nb_joueur_actif==2))
		{
			random=DrlmntPartie_Random(nb_joueur_actif);
			//printf("InitPartie_InitPartie : random=%d\n",random);
			if(random==0)
			{
				printf("InitPartie_InitPartie : Erreur de la fonction 'DrlmntPartie_Random' !\n");
				return -1;
			}
////////////////////////////////////////////////////////////////////////////////////////////////////////			
			if(random==1 && valid[0]==0)
			{
				test=DrlmntPartie_Distribution(table,J1);
				if(test==-1)
				{
					printf("InitPartie_InitPartie : Erreur dans DrlmntPartie_Distribution !\n");
					return -1;
				}
				valid[0]=1;
				//printf("InitPartie_InitPartie : valid[0]=1 ;\n");
			}
///////////////////////////////////////////////////////////////////////////////////////////////////////
			if(random==2 && valid[1]==0)
			{
				test=DrlmntPartie_Distribution(table,J2);
				if(test==-1)
				{
					printf("InitPartie_InitPartie : Erreur dans DrlmntPartie_Distribution !\n");
					return -1;
				}
				valid[1]=1;
				//printf("InitPartie_InitPartie : valid[1]=1 ;\n");
			}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
			if(random==3 && valid[2]==0)
			{
				test=DrlmntPartie_Distribution(table,J3);
				if(test==-1)
				{
					printf("InitPartie_InitPartie : Erreur dans DrlmntPartie_Distribution !\n");
					return -1;
				}
				valid[2]=1;
				//printf("InitPartie_InitPartie : valid[2]=1 ;\n");
			}
////////////////////////////////////////////////////////////////////////////////////////////////////////
			if(random==4 && valid[3]==0)
			{
				test=DrlmntPartie_Distribution(table,J4);
				if(test==-1)
				{
					printf("InitPartie_InitPartie : Erreur dans DrlmntPartie_Distribution !\n");
					return -1;
				}
				valid[3]=1;
				//printf("InitPartie_InitPartie : valid[3]=1\n");
			}
		}
		i++;
		memset(valid,0,sizeof(valid));
	}
	
	if(nb_joueur_actif==3) // car si 3 joueurs joue il y aura un joueur avec uen carte supplémentaire !
	{
		test=DrlmntPartie_EchgFIFOin(table,J1);
		if(test==-1)
		{
			printf("InitPartie_InitPartie : Erreur dans 'DrlmntPartie_EchgFIFOin' \n");
			return -1;
		}
	}
	
	return 0;
}


/*************************************************************************
**  InitPartie_Free_Carte			                		    		**
**  Description de la fonction	:free toutes les 
	paquets de cartes 													**
**																		**
**	Entrees : FIFO_PAQUET --> FIFO du paquet "table" 					**
**			  FIFO_PAQUET --> FIFO du paquet "J1" 	
			  FIFO_PAQUET --> FIFO du paquet "J2" 
			  FIFO_PAQUET --> FIFO du paquet "J3" 
			  FIFO_PAQUET --> FIFO du paquet "J4" 						**
**																		**
**	Sorties : int --> si -1=Erreur // si 0-OK							**
**									                                    **
**									                                    **
**************************************************************************/
int InitPartie_Free_Carte(FIFO_PAQUET *table, FIFO_PAQUET *J1,FIFO_PAQUET *J2,FIFO_PAQUET *J3,FIFO_PAQUET *J4)
{
	int test=-1;
	
	//printf("InitPartie_Free_Carte : Début fonction !\n");
	if(table->nb_carte!=0)
	{
		test=InitPartie_Free_Paquet(table);
		if(test==-1)
			return -1;
	}
	
	if(J1->nb_carte!=0)
	{
		test=InitPartie_Free_Paquet(J1);
		if(test==-1)
			return -1;
	}
	
	if(J2->nb_carte!=0)
	{
		test=InitPartie_Free_Paquet(J2);
		if(test==-1)
			return -1;
	}
	
	if(J3->nb_carte!=0)
	{
		test=InitPartie_Free_Paquet(J3);
		if(test==-1)
			return -1;
	}
	
	if(J4->nb_carte!=0)
	{
		test=InitPartie_Free_Paquet(J4);
		if(test==-1)
			return -1;
	}
	
	if(table->nb_carte==0 && J1->nb_carte==0 && J2->nb_carte==0 && J3->nb_carte==0 && J4->nb_carte==0)
	{
		//printf("InitPartie_Free_Carte : Tous les paquets sont vides !\n");
		//printf("InitPartie_Free_Carte : Fin fonction !\n");
		return 0;
	}
	//printf("InitPartie_Free_Carte : Fin fonction MAIS IL Y A UNE ERREUR !!!\n");
	return -1;
}

/*************************************************************************
**  InitPartie_Free_Paquet			                		    		**
**  Description de la fonction	:free toutes les 
	cartes d'un paquet 													**
**																		**
**	Entrees : FIFO_PAQUET --> FIFO du paquet "FIFO" 					**
**			  															**
**																		**
**	Sorties : int --> si -1=Erreur // si 0-OK							**
**									                                    **
**									                                    **
**************************************************************************/
int InitPartie_Free_Paquet(FIFO_PAQUET *FIFO)
{
	S_CARTE *carte=NULL;
	
	//printf("InitPartie_Free_Paquet : Début fonction !\n");
	while(FIFO->nb_carte!=0 && FIFO->carte_in!=NULL && FIFO->carte_out!=NULL)
	{
		carte=FIFO->carte_in;
		FIFO->carte_in=FIFO->carte_in->carte_suivante;
		FIFO->nb_carte=FIFO->nb_carte-1;
		//printf("InitPartie_Free_Paquet : nb_carte=%d\n",FIFO->nb_carte);
		
		if(FIFO->carte_in==FIFO->carte_out)
		{
			free(carte);
			FIFO->carte_in=NULL;
			FIFO->carte_out=NULL;
			//printf("InitPartie_Free_Paquet : Paquets vides !\n");
			FIFO->nb_carte=FIFO->nb_carte-1;
			/*printf("OK\n");
			DrlmntPartie_AfficheFIFO(FIFO);*/
			return 0;
		}
		free(carte);
	}
	//printf("InitPartie_Free_Paquet : Fin fonction avec ERREUR !\n");
	return 0;
}
/*************************************************************************
**  [InitPartie_ConfigurerPartie]                                       **
**  Permet d'editer les faits pour configurer la partie et ses          **
**  parametres (nb IA, niveau de difficulte par exemple)                **
**                                                                      **
**      Entrees : CHAR                                                  **
**                'C' pour configurer                                   **
**                'R' pour reinitialiser                                **
**                                                                      **
**      Sorties : /                                                     **
**                                                                      **
**************************************************************************/
void InitPartie_ConfigurerPartie(char indic)
{
	int retour=0;
	FILE *fp=NULL;
	if(indic=='C' || indic=='c')
	{
		retour=InitPartie_EditerConfig();
		if(retour==0)
		{
			printf("Erreur de configuration des faits (aucun fich. de faits ?) ...");
			printf("Retablissement de la config par defaut\n");
			if((fp=fopen("Faits","r")))
			{
				fclose(fp);
				InitPartie_ConfigFailSolver('R');
			}
			else
				InitPartie_ConfigFailSolver('C');
		}
	}
	else if(indic=='R' || indic=='r')
	{
		if((fp=fopen("Faits.SAVE","r")))
		{
			retour=InitPartie_ReinitConfigDefaut();
			if(retour==0)
			{
				printf("Erreur de reinitialisation de la configuration ...");
				printf("Retablissement de la config par defaut\n");
				if((fp=fopen("Faits","r")))
				{
					fclose(fp);
					InitPartie_ConfigFailSolver('R');
				}
				else
					InitPartie_ConfigFailSolver('C');
			}
		}
	}
}

/*************************************************************************
**  [InitPartie_EditerConfig]                                           **
**  Permet de dupliquer le fichier de faits afin de pouvoir le          **
**  modifier pour configurer la partie (nb IA, difficulte, ...)         **
**                                                                      **
**      Entrees : /                                                     **
**                                                                      **
**      Sorties : INT                                                   **
**                0 = echec                                             **
**                1 = succes                                            **
**                                                                      **
**************************************************************************/
int InitPartie_EditerConfig(void)
{
	FILE *fp=NULL;
	int retour=0;
	int nb=0;
	char str[MAXSIZE];
	memset(str,0,MAXSIZE*sizeof(char));
	
	retour=InitPartie_ClonnageFaits('C');
	if(retour==1)
	{
		fp=CreerListeCh_OuvrirFic(Fic_Faits,"w+"); //écrasé lors de l'ouverture
		if(fp!=NULL)
		{
			while(nb<1 || nb>3)
			{
				printf("Combien d'IA voulez vous affronter (entre 1 et 3) : ");
				scanf("%d",&nb);
				getchar();	
			}
			printf(" >Vous avez choisis %d adversaires\n",nb);
			strcpy(str,"Nb_J1;\r\n");
			fwrite(str,(int)strlen(str),1,fp);
			switch(nb)
			{
				case 1 : strcpy(str,"Nb_IA1;\r\n");
					 break;
				case 2 : strcpy(str,"Nb_IA2;\r\n");
					 break;
				case 3 : strcpy(str,"Nb_IA3;\r\n");
					 break;
				default : printf("Erreur !\n");
			}
			fwrite(str,(int)strlen(str),1,fp);
			nb=0;
			while(nb!=1 && nb!=2 && nb!=3)
			{
				printf("Choisissez la difficulte : 1- Easy / 2- Medium / 3- Hard\n");
				scanf("%d",&nb);
				getchar();	
			}
			switch(nb)
			{
				case 1 : strcpy(str,"Easy;\r\n");
					 break;
				case 2 : strcpy(str,"Medium;\r\n");
					 break;
				case 3 : strcpy(str,"Hard;\r\n");
					 break;
				default : printf("Erreur !\n");
			}
			fwrite(str,(int)strlen(str),1,fp);
			CreerListeCh_FermerFichier(fp);
		}
	}
	return retour;
}

/*************************************************************************
**  [InitPartie_ReinitConfigDefaut]                                     **
**  Permet de supprimer le clone du fichier de faits et de remettre     **
**  la config par defaut                                                **
**                                                                      **
**      Entrees : /                                                     **
**                                                                      **
**      Sorties : INT                                                   **
**                0 = echec                                             **
**                1 = succes                                            **
**                                                                      **
**************************************************************************/
int InitPartie_ReinitConfigDefaut(void)
{
	int retour;
	
	retour=InitPartie_ClonnageFaits('S');
	if (retour==1)
		return 1;
	else
		return 0;
}

/*************************************************************************
**  [InitPartie_ClonnageFaits]                                          **
**  Permet de cloner le fichier de faits pour modifier la config tout   **
**  en gardant quelquepart (le clone) la config par defaut              **
**                                                                      **
**      Entrees : CHAR                                                  **
**                'C' pour clonner le fichier                           **
**                'S' pour supprimer le clone                           **
**                                                                      **
**      Sorties : INT                                                   **
**                0 = echec                                             **
**                1 = succes                                            **
**                                                                      **
**************************************************************************/
int InitPartie_ClonnageFaits(char indic)
{
	if(indic=='C' || indic=='c')
	{
		if(!(system("cp Faits Faits.SAVE 2> /dev/null")))
			return 1; //copie cree
			
		return 0; //erreur
	}
	else if(indic=='S' || indic=='s')
	{
		if(!(system("rm Faits 2> /dev/null")) && !(system("mv Faits.SAVE Faits 2> /dev/null")))
			return 1; //suppression reussie
		
		return 0; //erreur
	}
	return 0;
}

/*************************************************************************
**  [InitPartie_ConfigFailSolver]                                       **
**  Cette fonction est une fonction de secours qui permet en cas d'     **
**  erreur dans la config de pouvoir revenir a un fichier de faits      **
**  correct/pre-configure ou d'en recreer un s'il n'existe pas          **
**                                                                      **
**      Entrees : CHAR                                                  **
**                'C' pour (re)créer un fic. de faits predefini s'il    **
**                    n'existe pas                                      **
**                'R' pour reinitialiser la config par defaut           **
**                                                                      **
**      Sorties : /                                                     **
**                                                                      **
**************************************************************************/
void InitPartie_ConfigFailSolver(char indic)
{
	FILE *fp=NULL;
	char str[MAXSIZE];
	
	if(indic=='C' || indic=='c')
	{
		fp=CreerListeCh_OuvrirFic("Faits","w+");
		   memset(str,0,MAXSIZE*sizeof(char));
		   strcpy(str,"Nb_J1;\r\n");
		   fwrite(str,(int)strlen(str),1,fp);
		   strcpy(str,"Nb_IA3;\r\n");
		   fwrite(str,(int)strlen(str),1,fp);
		   strcpy(str,"Medium;\r\n");
		   fwrite(str,(int)strlen(str),1,fp);
		CreerListeCh_FermerFichier(fp);
	}
	else if(indic=='R' || indic=='r')
	{
		if((!(remove("Faits"))&&!(remove("Faits.SAVE"))) || !(remove("Faits")) || !(remove("Faits.SAVE")))
		{
			// suppression reussie
			if((fp=CreerListeCh_OuvrirFic("Faits","w+")))
			{
				memset(str,0,MAXSIZE*sizeof(char));
				strcpy(str,"Nb_J1;\r\n");
				fwrite(str,(int)strlen(str),1,fp);
				strcpy(str,"Nb_IA3;\r\n");
				fwrite(str,(int)strlen(str),1,fp);
				strcpy(str,"Medium;\r\n");
				fwrite(str,(int)strlen(str),1,fp);
				CreerListeCh_FermerFichier(fp);
			}
		}
		else
		{
			printf("Impossible de rétablir la config par defaut...\n");
			printf("Consultez la documentation ou adressez vous aux developpeurs de cette application\n");
		}
	}
}

/*************************************************************************
**  InitPartie_Compte_Joueur			                		    	**
**  Description de la fonction	: Détermine combien de FIFo sont "active"**
**																		**
**	Entrees : 										 					**
**			  FIFO_PAQUET --> FIFO du paquet "J1" 	
			  FIFO_PAQUET --> FIFO du paquet "J2" 
			  FIFO_PAQUET --> FIFO du paquet "J3" 
			  FIFO_PAQUET --> FIFO du paquet "J4" 						**
**																		**
**	Sorties : int --> si -1=Erreur // nombre de joueur ACTIF			**
**									                                    **
**									                                    **
**************************************************************************/
int InitPartie_Compte_Joueur(FIFO_PAQUET *J1,FIFO_PAQUET *J2,FIFO_PAQUET *J3,FIFO_PAQUET *J4)
{
	int i=0;
	
	if(J1->nom_joueur!=-1)
	{
		i++;	
	}
	
	if(J2->nom_joueur!=-1)
	{
		i++;	
	}
	
	if(J3->nom_joueur!=-1)
	{
		i++;	
	}
	
	if(J4->nom_joueur!=-1)
	{
		i++;	
	}
	
	return i;
}